/* 
 * Copyright [2018] [Alex/libo(liboware@gmail.com)]
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.infodb.gateway.service;

import java.util.ArrayList;
import java.util.Optional;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.annotation.Bean;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import com.hyts.infodb.gateway.bean.RouteDefinitionBO;
import com.hyts.infodb.gateway.bean.RouteDefinitionPO;
import com.hyts.infodb.gateway.bean.RouteDefinitionVO;
import com.hyts.infodb.gateway.dao.GatewayDAO;

/** 
 * @author LiBo/Alex
 * @version V1.0 
 */
@CacheConfig(cacheNames="coffice-gateway")
@Service
public class GatewayService implements ApplicationEventPublisherAware{
    
    @Autowired
    GatewayDAO gatewayDao;
    
    /**  
     * @fieldName publisher
     * @fieldType ApplicationEventPublisher
     */ 
    private ApplicationEventPublisher publisher;
    
    /**  
     * @exception
     */ 
    public void refreshRoute() {
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    @Bean
    public RouteLocator initRoute(RouteLocatorBuilder builder){
       return builder.routes().route("baidu",path->path.path("/bina").uri("https://www.cnblogs.com/weizhxa/p/6836246.html")).build();
    }

    /**
     * @return
     * @exception
     */ 
    @Cacheable
    public RouteDefinitionVO findAllGatewayDataList(){
        RouteDefinitionVO vo = new RouteDefinitionVO();
        vo.setContents(new ArrayList(gatewayDao.findAll()));
        return vo;
    }
    
    /**  
     * @param routeDefinitionBO
     * @return
     * @exception
     */ 
    @Cacheable
    public RouteDefinitionVO findGatewayDataList(RouteDefinitionBO routeDefinitionBO){
        RouteDefinitionVO vo = new RouteDefinitionVO();
        Page<RouteDefinitionPO> pageData = gatewayDao.findAll(routeDefinitionBO.buildPageData(routeDefinitionBO.getPageNum(), routeDefinitionBO.getPageSize()));
        vo.setContents(pageData.getContent());
        vo.setTotalDataSize(pageData.getTotalElements());
        vo.setTotalPageNumber(pageData.getTotalPages());
        return vo;
    }
    
    /**  
     * @param routeDefinitionBO
     * @return
     * @exception
     */ 
    @CachePut(key="#routeDefinitionBO.id")
    public boolean saveGatewayData(RouteDefinitionBO routeDefinitionBO) {
        RouteDefinitionPO po = new RouteDefinitionPO();
        routeDefinitionBO.buildDefaultPredicates(false,routeDefinitionBO.getPath());
        routeDefinitionBO.buildDefaultFilters(false,1);
        po.setPath(JSONObject.parseArray(routeDefinitionBO.getPredicates()).getJSONObject(0)
            .getJSONObject("args").getString("pattern"));
        BeanUtils.copyProperties(routeDefinitionBO, po);
        boolean result = Optional.ofNullable(gatewayDao.save(po)).isPresent();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return result;
    }
    
    /**  
     * @param routeDefinitionBO
     * @return
     * @exception
     */ 
    @CacheEvict(key="#routeDefinitionBO.id")
    public boolean deleteGatewayData(RouteDefinitionBO routeDefinitionBO) {
        RouteDefinitionPO po = new RouteDefinitionPO();
        BeanUtils.copyProperties(routeDefinitionBO, po);
        try {
            gatewayDao.delete(po);
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        } catch (Exception e) {
            return false;
        }
        return true; 
    }
    
    
    /**  
     * @param routeDefinitionBO
     * @return
     * @exception
     */ 
    @Cacheable(key="#routeDefinitionBO.id")
    public RouteDefinitionPO loadGatewayData(RouteDefinitionBO routeDefinitionBO) {
        try {
            Optional<RouteDefinitionPO> po = gatewayDao.findById(routeDefinitionBO.getId());
            return po.get();
        } catch (Exception e) {
            return null;
        }
    }

    /**  
     * @name publisher's getter method
     * @return publisher
     */
    public ApplicationEventPublisher getPublisher() {
        return publisher;
    }

    /* (非 Javadoc)
     * @param applicationEventPublisher
     * @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher)  
     * @exception
     */ 
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

}
